
package nsga;

import java.io.BufferedReader;
import java.io.FileReader;

public class TSP implements Problema
{
    private double[][] distancias;
    private double[][] tiempos;
    private int length;
    private int cantidadDigitos;
    private int TIPO = 0;

    public TSP(double[][] distancias, double[][] tiempos)
    {
        this.distancias = distancias;
        this.tiempos = tiempos;
        length=distancias.length;
        cantidadDigitos=(int)Math.pow(10, String.valueOf(length).length());
    }
    
    public void setFitness(Individuo individuo)
    {
        double[] result=new double[2];
        int[] grafo=((IndividuoTSP)individuo).getGrafo();
        int actual=0;
        for(int i=0;i<length;i++)
        {
            result[0]+=distancias[actual][grafo[actual]];
            result[1]+=tiempos[actual][grafo[actual]];
            actual=grafo[actual];
        }
        individuo.setFitness(result);
    }
    
    public Individuo[] cruzar(Individuo individuo1,Individuo individuo2)
    {
        IndividuoTSP[] result= new IndividuoTSP[2];
        result[0]=new IndividuoTSP(length);
        result[1]=new IndividuoTSP(length);
        int[] grafo1=((IndividuoTSP)individuo1).getGrafo();
        int[] grafo2=((IndividuoTSP)individuo2).getGrafo();
        boolean turno=false;
        int actual=0;
        do
        {
            if(!turno)
            {
                if(result[0].addNodo(grafo1[actual]))
                {
                    actual=grafo1[actual];
                }
                else if(result[0].addNodo(grafo2[actual]))
                {
                    actual=grafo2[actual];
                }
                else
                {
                    do
                    {
                        int rand;
                        do
                        {
                            rand=((int)(Math.random()*cantidadDigitos));
                        }
                        while((rand>=this.length)||(grafo1[actual]==rand)||(grafo2[actual]==rand));
                        if(result[0].addNodo(rand))
                        {
                               actual=rand;
                               break;
                        }
                    }
                    while(true);
                }
            }
            else
            {
                if(result[0].addNodo(grafo2[actual]))
                {
                    actual=grafo2[actual];
                }
                else if(result[0].addNodo(grafo1[actual]))
                {
                    actual=grafo1[actual];
                }
                else
                {
                    do
                    {
                        int rand;
                        do
                        {
                            rand=((int)(Math.random()*cantidadDigitos));
                        }
                        while((rand>=this.length)||(grafo2[actual]==rand)||(grafo1[actual]==rand));
                        if(result[0].addNodo(rand))
                        {
                               actual=rand;
                               break;
                        }
                    }
                    while(true);
                }
            }
            turno=!turno;
        }
        while(!result[0].isFull());
        turno=false;
        actual=0;
        do
        {
            if(!turno)
            {
                if(result[1].addNodo(grafo2[actual]))
                {
                    actual=grafo2[actual];
                }
                else if(result[1].addNodo(grafo1[actual]))
                {
                    actual=grafo1[actual];
                }
                else
                {
                    do
                    {
                        int rand;
                        do
                        {
                            rand=((int)(Math.random()*cantidadDigitos));
                        }
                        while((rand>=this.length)||(grafo2[actual]==rand)||(grafo1[actual]==rand));
                        if(result[1].addNodo(rand))
                        {
                               actual=rand;
                               break;
                        }
                    }
                    while(true);
                }
            }
            else
            {
                if(result[1].addNodo(grafo1[actual]))
                {
                    actual=grafo1[actual];
                }
                else if(result[1].addNodo(grafo2[actual]))
                {
                    actual=grafo2[actual];
                }
                else
                {
                    do
                    {
                        int rand;
                        do
                        {
                            rand=((int)(Math.random()*cantidadDigitos));
                        }
                        while((rand>=this.length)||(grafo1[actual]==rand)||(grafo2[actual]==rand));
                        if(result[1].addNodo(rand))
                        {
                               actual=rand;
                               break;
                        }
                    }
                    while(true);
                }
            }
            turno=!turno;
        }
        while(!result[1].isFull());
        IndividuoTSP.isIndividuoValido(result[0]);
        IndividuoTSP.isIndividuoValido(result[1]);
        return result;
    }
    
    public static TSP main(String args)throws Exception
    {
        BufferedReader bufferedReader=new BufferedReader(new FileReader(args));
        int length=Integer.parseInt(bufferedReader.readLine());
        bufferedReader.readLine();
        double[][] distancias=new double[length][length];
        for(int i=0;i<length;i++)
        {
            String[] fila=bufferedReader.readLine().split("\\s");
            for(int j=0;j<fila.length;j++)
            {
                distancias[i][j]=Double.parseDouble(fila[j]);
            }
        }
        bufferedReader.readLine();
        double[][] tiempos=new double[length][length];
        for(int i=0;i<length;i++)
        {
            String[] fila=bufferedReader.readLine().split("\\s");
            for(int j=0;j<fila.length;j++)
            {
                tiempos[i][j]=Double.parseDouble(fila[j]);
            }
        }
        return new TSP(distancias, tiempos);
    }

    public int getLength()
    {
        return length;
    }
    
    public int getTipo()
    {
        return TIPO;
    }
}